/*
    异步处理的缓冲区类
*/

#pragma once
#include "Util.hpp"
#include <memory>
#include <utility>
#include <cstddef> 
#include <vector>
#include <cassert>

namespace XKL
{
    class Buffer
    {
    public:
        using ptr = std::shared_ptr<Buffer>;
        Buffer()
            : _read_index(0), _write_index(0)
        {
            Util::File::BufferInit(_default_size, _threshold_size, _increment_size);
            _buffer.resize(_default_size);
        }

        void push(const char* data, size_t len) // 缓冲区不够和写满的情况 阻塞/返回false 扩容极限测试
        {
            // 缓冲区剩余空间不够或写满了：
            // 扩容 动态空间 
            EnsureEnoughSize(len);
            std::copy(data, data + len, &_buffer[_write_index]);
            MoveWriter(len);
        }

        const char* begin()
        {
            return &_buffer[_read_index];
        }

        size_t WriteAbleSize()
        {
            return _buffer.size() - _write_index;
        }

        size_t ReadAbleSize()
        {
            return _write_index - _read_index;
        }

        void MoveReader(size_t len)
        {
            assert(len <= ReadAbleSize());
            _read_index += len;
        }

        void MoveWriter(size_t len)
        {
            assert(len <= WriteAbleSize());
            _write_index += len;
        }

        void Swap(Buffer& buff) // 交换缓冲区
        {
            _buffer.swap(buff._buffer); // 待定

            std::swap(_read_index, buff._read_index);
            std::swap(_write_index, buff._write_index);
        }

        bool Empty()
        {
            return _write_index == _read_index;
        }

        void Rest()
        {
            _read_index = 0;
            _write_index = 0;
        }
    private:
        void EnsureEnoughSize(size_t len)
        {
            if(len < WriteAbleSize())
                return ;
            
            size_t new_size = 0;
            // 加len的原因：防止扩容后依旧不满足（简单处理）
            if(_buffer.size() > _threshold_size)
            {
                new_size = _buffer.size() * 2 + len;
            }
            else
            {
                new_size = _buffer.size() + _increment_size + len;
            }
            _buffer.resize(new_size);
        }

    private:
        size_t _read_index;
        size_t _write_index;
        size_t _default_size;
        size_t _threshold_size;
        size_t _increment_size;
        std::vector<char> _buffer;
    };
}